package com.androidvizlab.bachelor.datamodels;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;

import android.util.Log;

import com.androidvizlab.bachelor.Interface.DataChangeEvent;
import com.androidvizlab.bachelor.Interface.IObservable;
import com.androidvizlab.bachelor.Interface.Observer;
import com.androidvizlab.bachelor.Interface.OptionsFileDataChangeEvent;

/**
 * A Base class that represents the options-file.
 * 
 * @author TheHive
 */
public class OptionsFile implements IObservable{
	
	//Enum used to determine runtype: Calibration, production and recalculation
	public enum RunType
	{
		CALIBRATION("C"),PRODUCTION("P"),RECALCULATION("R");
		
		private String runType;
		
		private RunType(String runType)
		{
			this.runType = runType;
		}
	
		public String getRunType()
		{
			return runType;
		}
	}
	
	private Set<Observer> observers;
	
	public OptionsFile()
	{
		observers = new HashSet<Observer>();
	}

	//*** General Option ***//
	private String calibrationFilePath = "";
	private RunType runType = RunType.CALIBRATION;
	private String calibrationFileName = "";
	private int triggingInterval = 0;
	private int numTripletCamGrp = 0;
	private int numTimePts = 0;
	private int numMarkers = 0;
	private boolean programOutputSocketConnection = false;
	
	//*** Advanced Option ***//
	
	private int offsetPix;
	private int minpix;
	private int maxpix;
	private int minsep;
	private int maxerr;
	
	//Image file Input/Output
	private boolean imgFileInputTriplets = false;
	private boolean imgFileInputTripletsTurnedRight = false;
	private boolean imgFileOutputOriginalImg = false;
	private boolean imgFileOutputGeneratedTriplets = false;
	private boolean imgFileOutputGeneratedTripletsTurnedRight = false;
	
	//Help file
	private boolean helpFileOutputImageDetectPoints = true;
	private boolean helpFileOutputDuplicatePoints = true;
	private boolean helpFileOutputMatch3 = true;
	private boolean helpFileOutputdobbelMatch = true;
	private boolean helpFileOutputConnectPoints = true;
	private boolean helpFileOutputTimeseries = true;
	private double approxFrameMarkerLimit = 0;
	
	//*** GETTERS AND SETTERS ***//
	
	public String getCalibrationFilePath() {
		return calibrationFilePath;
	}

	public void setCalibrationFilePath(String calibrationFilePath) {
		this.calibrationFilePath = calibrationFilePath;
		
		notifyObservers();
	}

	public RunType getRunType() {
		return runType;
	}

	public void setRunType(RunType runType) {
		this.runType = runType;
		
		notifyObservers();
	}

	public String getCalibrationFileName() {
		return calibrationFileName;
	}

	public void setCalibrationFileName(String calibrationFileName) {
		this.calibrationFileName = calibrationFileName;
		
		notifyObservers();
	}

	public int getTriggingInterval() {
		return triggingInterval;
	}

	public void setTriggingInterval(int triggingInterval) {
		this.triggingInterval = triggingInterval;
		
		notifyObservers();
	}

	public int getNumTripletCamGrp() {
		return numTripletCamGrp;
	}

	public void setNumTripletCamGrp(int numTripletCamGrp) {
		this.numTripletCamGrp = numTripletCamGrp;
	
		notifyObservers();
	}

	public int getNumTimePts() {
		return numTimePts;
	}

	public void setNumTimePts(int numTimePts) {
		this.numTimePts = numTimePts;
	
		notifyObservers();
	}

	public int getNumMarkers() {
		return numMarkers;
	}

	public void setNumMarkers(int numMarkers) {
		this.numMarkers = numMarkers;
		
		notifyObservers();
	}

	public boolean isProgramOutputSocketConnection() {
		return programOutputSocketConnection;
	}

	public void setProgramOutputSocketConnection(
			boolean programOutputSocketConnection) {
		this.programOutputSocketConnection = programOutputSocketConnection;
		
		notifyObservers();
	}
	
	public int getOffsetPix() {
		return offsetPix;
	}

	public void setOffsetPix(int offsetPix) {
		this.offsetPix = offsetPix;
		
		notifyObservers();
	}

	public int getMinpix() {
		return minpix;
	}

	public void setMinpix(int minpix) {
		this.minpix = minpix;
		
		notifyObservers();
	}

	public int getMaxpix() {
		return maxpix;
	}

	public void setMaxpix(int maxpix) {
		this.maxpix = maxpix;
		
		notifyObservers();
	}

	public int getMinsep() {
		return minsep;
	}

	public void setMinsep(int minsep) {
		this.minsep = minsep;
		
		notifyObservers();
	}

	public int getMaxerr() {
		return maxerr;
	}

	public void setMaxerr(int maxerr) {
		this.maxerr = maxerr;
		
		notifyObservers();
	}

	public boolean isImgFileInputTriplets() {
		return imgFileInputTriplets;
	}

	public void setImgFileInputTriplets(boolean imgFileInputTriplets) {
		this.imgFileInputTriplets = imgFileInputTriplets;
		
		notifyObservers();
	}

	public boolean isImgFileInputTripletsTurnedRight() {
		return imgFileInputTripletsTurnedRight;
	}

	public void setImgFileInputTripletsTurnedRight(
			boolean imgFileInputTripletsTurnedRight) {
		this.imgFileInputTripletsTurnedRight = imgFileInputTripletsTurnedRight;
		
		notifyObservers();
	}

	public boolean isImgFileOutputOriginalImg() {
		return imgFileOutputOriginalImg;
	}

	public void setImgFileOutputOriginalImg(boolean imgFileOutputOriginalImg) {
		this.imgFileOutputOriginalImg = imgFileOutputOriginalImg;
		
		notifyObservers();
	}

	public boolean isImgFileOutputGeneratedTriplets() {
		return imgFileOutputGeneratedTriplets;
	}

	public void setImgFileOutputGeneratedTriplets(
			boolean imgFileOutputGeneratedTriplets) {
		this.imgFileOutputGeneratedTriplets = imgFileOutputGeneratedTriplets;
		
		notifyObservers();
	}

	public boolean isImgFileOutputGeneratedTripletsTurnedRight() {
		return imgFileOutputGeneratedTripletsTurnedRight;
	}

	public void setImgFileOutputGeneratedTripletsTurnedRight(
			boolean imgFileOutputGeneratedTripletsTurnedRight) {
		this.imgFileOutputGeneratedTripletsTurnedRight = imgFileOutputGeneratedTripletsTurnedRight;
	
		notifyObservers();
	}

	public boolean isHelpFileOutputImageDetectPoints() {
		return helpFileOutputImageDetectPoints;
	}

	public void setHelpFileOutputImageDetectPoints(
			boolean helpFileOutputImageDetectPoints) {
		this.helpFileOutputImageDetectPoints = helpFileOutputImageDetectPoints;
		
		notifyObservers();
	}

	public boolean isHelpFileOutputDuplicatePoints() {
		return helpFileOutputDuplicatePoints;
	}

	public void setHelpFileOutputDuplicatePoints(
			boolean helpFileOutputDuplicatePoints) {
		this.helpFileOutputDuplicatePoints = helpFileOutputDuplicatePoints;
		
		notifyObservers();
	}

	public boolean isHelpFileOutputMatch3() {
		return helpFileOutputMatch3;
	}

	public void setHelpFileOutputMatch3(boolean helpFileOutputMatch3) {
		this.helpFileOutputMatch3 = helpFileOutputMatch3;
		
		notifyObservers();
	}

	public boolean isHelpFileOutputdobbelMatch() {
		return helpFileOutputdobbelMatch;
	}

	public void setHelpFileOutputdobbelMatch(boolean helpFileOutputdobbelMatch) {
		this.helpFileOutputdobbelMatch = helpFileOutputdobbelMatch;
		
		notifyObservers();
	}

	public boolean isHelpFileOutputConnectPoints() {
		return helpFileOutputConnectPoints;
	}

	public void setHelpFileOutputConnectPoints(boolean helpFileOutputConnectPoints) {
		this.helpFileOutputConnectPoints = helpFileOutputConnectPoints;
		
		notifyObservers();
	}

	public boolean isHelpFileOutputTimeseries() {
		return helpFileOutputTimeseries;
	}

	public void setHelpFileOutputTimeseries(boolean helpFileOutputTimeseries) {
		this.helpFileOutputTimeseries = helpFileOutputTimeseries;
		
		notifyObservers();
	}

	public double getApproxFrameMarkerLimit() {
		return approxFrameMarkerLimit;
	}

	public void setApproxFrameMarkerLimit(double approxFrameMarkerLimit) {
		this.approxFrameMarkerLimit = approxFrameMarkerLimit;
		
		notifyObservers();
	}
	
	//*** FROM IObservable interface ***//
	
	@Override
	public synchronized void addObserver(Observer observer) {
		observers.add(observer);
	}

	@Override
	public synchronized void addObservers(ArrayList<Observer> list) {
		
		if(list != null && list.size() > 0)
		{
			for(Observer obs : list)
			{
				observers.add(obs);
			}
		}
	}
	
	@Override
	public synchronized void removeObserver(Observer observer) {
		observers.remove(observer);
	}
	
	@Override
	public synchronized void removeAllObservers() {
		observers.clear();
	}
	
	@Override
	public synchronized void notifyObservers() {
		
		OptionsFileDataChangeEvent e = new OptionsFileDataChangeEvent(this);
		
		for(Observer obs : observers)
		{
			obs.update(e);
		}
	}
	
	@Override
	public synchronized void notifyObservers(Object object) {
		
		OptionsFileDataChangeEvent e = new OptionsFileDataChangeEvent(this);
		
		for(Observer obs : observers)
		{
			obs.update(e,object);
		}
	}
}
